package com.dcy.system.biz.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.dcy.common.constant.Constant;
import com.dcy.db.base.service.BaseService;
import com.dcy.system.api.api.AUserService;
import com.dcy.system.api.model.Role;
import com.dcy.system.api.model.UserInfo;
import com.dcy.system.api.model.UserPost;
import com.dcy.system.api.model.UserRole;
import com.dcy.system.biz.component.DataScopeUtil;
import com.dcy.system.biz.mapper.UserInfoMapper;
import com.dcy.system.biz.mapper.UserPostMapper;
import com.dcy.system.biz.mapper.UserRoleMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author dcy
 * @since 2020-08-19
 */
@DubboService(version = "1.0.0", timeout = 3000, interfaceClass = AUserService.class)
public class UserInfoService extends BaseService<UserInfoMapper, UserInfo> implements AUserService {

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserPostMapper userPostMapper;
    @Autowired
    private DataScopeUtil dataScopeUtil;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 根据用户名获取用户信息
     *
     * @param username
     * @return
     */
    public UserInfo getUserInfoByUsername(String username) {
        return super.getOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getUsername, username).last("LIMIT 1"));
    }

    /**
     * 根据用户id 查询已授权角色列表
     *
     * @param userId
     * @return
     */
    public List<Role> getAuthRoleListByUserId(String userId) {
        return baseMapper.getAuthRoleListByUserId(userId);
    }

    @Override
    public Set<String> getResourcesCodeByUserId(String userId) {
        Set<String> resourcesCodeByUserId = baseMapper.getResourcesCodeByUserId(userId);
        // 缓存权限
        redisTemplate.opsForValue().set(Constant.REDIS_RESOURCE_CODE+userId, resourcesCodeByUserId, 30, TimeUnit.MINUTES);
        return resourcesCodeByUserId;
    }

    @Override
    public Set<String> getAuthRoleKeyByUserId(String userId) {
        Set<String> authRoleKeyByUserId = baseMapper.getAuthRoleKeyByUserId(userId);
        // 缓存角色
        redisTemplate.opsForValue().set(Constant.REDIS_ROLE_KEY+userId, authRoleKeyByUserId, 30, TimeUnit.MINUTES);
        return authRoleKeyByUserId;
    }

    /**
     * 保存授权角色
     *
     * @param userId  用户id
     * @param roleIds 授权角色Ids
     * @return
     */
    @CacheEvict(value = {"role:data-scope", "role:data-scope-flag"}, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveAuthRole(String userId, List<String> roleIds) {
        boolean success = false;
        if (StrUtil.isNotBlank(userId) && roleIds != null) {
            // 删除关联表
            userRoleMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, userId));
            // 添加关联表
            List<UserRole> userRoles = new ArrayList<>();
            roleIds.forEach(roleId -> userRoles.add(new UserRole().setUserId(userId).setRoleId(roleId)));
            SqlHelper.executeBatch(UserRole.class, this.log, userRoles, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {
                String sqlStatement = SqlHelper.getSqlStatement(UserRoleMapper.class, SqlMethod.INSERT_ONE);
                sqlSession.insert(sqlStatement, entity);
            });
            success = true;
        }
        // 清空权限
        Set<String> keys = redisTemplate.keys(Constant.REDIS_ROLE_KEY + "*");
        redisTemplate.delete(keys);
        return success;
    }

    /**
     * 获取用户分页数据多条件查询
     *
     * @param userInfo
     * @return
     */
    public IPage<UserInfo> getPageListByEntity(UserInfo userInfo) {
        QueryWrapper<UserInfo> queryWrapper = Wrappers.<UserInfo>query();
        queryWrapper.like(StrUtil.isNotBlank(userInfo.getUsername()), UserInfo.USERNAME, userInfo.getUsername());
        if (StrUtil.isNotBlank(userInfo.getDeptId())) {
            // u.dept_id = 100 OR u.dept_id IN  (SELECT t.dept_id FROM sys_dept t WHERE FIND_IN_SET(100, ancestors)
            queryWrapper.and(userInfoQueryWrapper -> {
                        userInfoQueryWrapper.eq(UserInfo.DEPT_ID, userInfo.getDeptId())
                                .or().inSql(UserInfo.DEPT_ID, "SELECT sys_dept.id FROM sys_dept WHERE FIND_IN_SET('" + userInfo.getDeptId() + "', ancestors)");
                    }
            );
        }
        // 添加数据权限
        dataScopeUtil.dataScopeFilter(queryWrapper);
        return super.page(userInfo, queryWrapper);
    }

    /**
     * 保存用户和保存岗位
     *
     * @param userInfo
     * @param postIds
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUser(UserInfo userInfo, List<String> postIds) {
        boolean success = false;
        if (super.saveOrUpdate(userInfo)) {
            userPostMapper.delete(Wrappers.<UserPost>lambdaQuery().eq(UserPost::getUserId, userInfo.getId()));
            List<UserPost> userPosts = new ArrayList<>();
            postIds.forEach(s -> userPosts.add(new UserPost().setUserId(userInfo.getId()).setPostId(s)));
            SqlHelper.executeBatch(UserPost.class, this.log, userPosts, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {
                String sqlStatement = SqlHelper.getSqlStatement(UserPostMapper.class, SqlMethod.INSERT_ONE);
                sqlSession.insert(sqlStatement, entity);
            });
            success = true;
        }
        return success;
    }

    /**
     * 根据用户id 查询岗位id
     *
     * @param userId
     * @return
     */
    public List<String> getPostListByUserId(String userId) {
        List<String> list = new ArrayList<>();
        List<UserPost> userPosts = userPostMapper.selectList(Wrappers.<UserPost>lambdaQuery().eq(UserPost::getUserId, userId));
        if (CollUtil.isNotEmpty(userPosts)) {
            list = userPosts.stream().map(UserPost::getPostId).collect(Collectors.toList());
        }
        return list;
    }
}
